<template>
    <div class="dndflow">
        <Sidebar />

        <VueFlow v-model="state.elements" class="examine-design-container" @connect="onConnect" @drop="onDrop"
            @nodeClick="nodeClickHandler" @dragover="onDragOver">
            <Background v-if="state.showGrid" />
            <SaveRestoreControls @addNode="addNode" @restore="restore" />
            <Controls />
            <MiniMap class="examine-design-minimap" v-if="state.showMiniMap" />
            <template #node-custom="{ data }">
                <customNode :data="data" />
            </template>
            <template #connection-line="{ sourceX, sourceY, targetX, targetY }">
                <CustomConnectionLine :source-x="sourceX" :source-y="sourceY" :target-x="targetX" :target-y="targetY" />
            </template>
        </VueFlow>
    </div>
</template>

<!-- Flowchart.vue -->
<script setup lang="ts">
import { VueFlow, useVueFlow } from '@vue-flow/core'
import { nextTick, reactive, watch } from 'vue';
import { Background, MiniMap, Controls } from '@vue-flow/additional-components'
import { ElMessage } from 'element-plus';
import customNode from './customNode.vue'
import CustomConnectionLine from './customConnectionLine.vue'
import SaveRestoreControls from './saveRestoreControls.vue'
import Sidebar from './sidebar.vue'

const { nodes, addNodes, setNodes, setEdges, dimensions, setTransform, toObject, findNode, addEdges, project, vueFlowRef } = useVueFlow()
const state = reactive({
    // 网格显示
    showGrid: true,
    // 显示缩略图
    showMiniMap: true,
    elements: [
        { id: '1', type: 'start', label: '学生请假', position: { x: 100, y: 50 } },
        { id: '2', type: 'custom', data: { examineType: 1, examineList: [{ code: '1', name: '张三' }] }, label: '发起人', position: { x: 100, y: 150 } },
        { id: '3', type: 'custom', data: { examineType: 2, examineList: [{ code: '1', name: '班主任' }] }, label: '班主任审核', position: { x: 400, y: 150 } },
        { id: '4', type: 'custom', data: { examineType: 3, examineList: [{ code: '1', name: '教务处' }] }, label: '教务处审核', position: { x: 800, y: 150 } },
        { id: '5', type: 'output', label: '结束', position: { x: 100, y: 450 } },
        { id: 'e1-2', source: '1', target: '2' },
        { id: 'e1-3', source: '1', target: '3' },
        { id: 'e1-4', source: '1', target: '4' },
        { id: 'e2-5', source: '2', target: '5', animated: true },
        { id: 'e2-3', source: '2', target: '3', animated: true },
        { id: 'e2-4', source: '2', target: '4', animated: true },
        // { id: 'e4-5', source: '4', target: '5', animated: true },
    ],
})

const nodeClickHandler = (props: { node: any; }) => {
    const node = props.node;
    ElMessage({
        type: 'success',
        message: node
    })
};

const addNode = (type: number) => {

}
const restore = () => {
    state.elements = []
}
function onConnect(params: { source: any; target: any; }) {
    state.elements.push({
        id: `e${params.source}-${params.target}`,
        source: params.source,
        target: params.target
    })
}

function onDragOver(event) {
    event.preventDefault()

    if (event.dataTransfer) {
        event.dataTransfer.dropEffect = 'move'
    }
}

let id = 0
function getId() {
  return `dndnode_${id++}`
}

function onDrop(event) {
    const type = event.dataTransfer?.getData('application/vueflow')

    const { left, top } = vueFlowRef.value.getBoundingClientRect()

    const position = project({
        x: event.clientX - left,
        y: event.clientY - top,
    })

    const newNode = {
        id: getId(),
        type,
        position,
        label: `${type}`,
    }

    addNodes([newNode])

    // align node position after drop, so it's centered to the mouse
    nextTick(() => {
        const node = findNode(newNode.id)
        const stop = watch(
            () => node.dimensions,
            (dimensions) => {
                if (dimensions.width > 0 && dimensions.height > 0) {
                    node.position = { x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2 }
                    stop()
                }
            },
            { deep: true, flush: 'post' },
        )
    })
}

</script>


<style lang="less">
/* import the required styles */
@import "@vue-flow/core/dist/style.css";

/* import the default theme (optional) */
@import "@vue-flow/core/dist/theme-default.css";

.dndflow {
    flex-direction: column;
    display: flex;
    height: 100%
}

.dndflow aside {
    color: #fff;
    font-weight: 700;
    border-right: 1px solid #eee;
    padding: 15px 10px;
    font-size: 12px;
    background: rgba(16, 185, 129, .75);
    -webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, .3);
    box-shadow: 0 5px 10px #0000004d
}

.dndflow aside .nodes>* {
    margin-bottom: 10px;
    cursor: grab;
    font-weight: 500;
    -webkit-box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, .25);
    box-shadow: 5px 5px 10px 2px #00000040
}

.dndflow aside .description {
    margin-bottom: 10px
}

.dndflow .vue-flow-wrapper {
    flex-grow: 1;
    height: 100%
}

@media screen and (min-width: 640px) {
    .dndflow {
        flex-direction: row
    }

    .dndflow aside {
        min-width: 15%
    }
}

@media screen and (max-width: 639px) {
    .dndflow aside .nodes {
        display: flex;
        flex-direction: row;
        gap: 5px
    }
}

.examine-design-container {
    background: 'transparent';

    :deep(.node-light) {
        background: green;
    }

    :deep(.node-dark) {
        background: red;
    }
}
</style>